package com.chucang.shucang.pms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chucang.shucang.common.base.constant.CommonConstant;
import com.chucang.shucang.common.base.constant.SecurityConstant;
import com.chucang.shucang.common.base.exception.FastException;
import com.chucang.shucang.common.base.page.PageData;
import com.chucang.shucang.common.base.page.PageQuery;
import com.chucang.shucang.common.base.redis.RedisUtil;
import com.chucang.shucang.common.base.service.impl.CrudServiceImpl;
import com.chucang.shucang.common.base.utils.OpsUtil;
import com.chucang.shucang.common.base.utils.R;
import com.chucang.shucang.pms.constant.PmsCacheConstant;
import com.chucang.shucang.pms.constant.PmsCommonConstant;
import com.chucang.shucang.pms.dao.BlindBoxMallDao;
import com.chucang.shucang.pms.dto.BlindBoxMallDTO;
import com.chucang.shucang.pms.entity.BlindBoxBaseEntity;
import com.chucang.shucang.pms.entity.BlindBoxMallEntity;
import com.chucang.shucang.pms.feign.UserService;
import com.chucang.shucang.pms.feign.vo.UserBaseEntity;
import com.chucang.shucang.pms.feign.vo.UserBlindBoxHoldEntity;
import com.chucang.shucang.pms.service.BlindBoxBaseService;
import com.chucang.shucang.pms.service.BlindBoxMallService;
import com.chucang.shucang.pms.vo.*;
import com.chucang.shucang.pms.vo.query.BlindBoxOnSaleQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


/**
 * 盲盒商城表
 *
 * @author flitsneak flitsneak@gmail.com
 * @since 1.0.0 2022-09-12
 */
@Service
@RequiredArgsConstructor
public class BlindBoxMallServiceImpl extends CrudServiceImpl<BlindBoxMallDao, BlindBoxMallEntity, BlindBoxMallDTO> implements BlindBoxMallService {

    private final BlindBoxBaseService blindBoxBaseService;
    private final UserService userService;
    private final RedisUtil redisUtil;

    @Override
    @Cacheable(value = "blindBoxMallInfo", key = "#id")
    public BlindBoxMallEntity getTheBottomPrice(Long id) {
        LambdaQueryWrapper<BlindBoxMallEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(BlindBoxMallEntity::getBbId, id)
                .ne(BlindBoxMallEntity::getStatus, PmsCommonConstant.COLLECTION_CONSIGN)
                .orderByAsc(BlindBoxMallEntity::getSellingPrice)
                .select(BlindBoxMallEntity::getBbId, BlindBoxMallEntity::getSellingPrice)
                .last("limit 1");
        return this.getOne(lambdaQueryWrapper);
    }

    @Override
    public BlindBoxOnSalePageResVO onSaleBlindBoxPage(BlindBoxOnSaleQuery blindBoxOnSaleQuery) {
        BlindBoxBaseEntity blindBoxBase = this.cacheBlindBoxBaseInfo(blindBoxOnSaleQuery.getId());

        BlindBoxBaseOnSaleResVO baseOnSaleResVO = new BlindBoxBaseOnSaleResVO();
        BeanUtil.copyProperties(blindBoxBase, baseOnSaleResVO);
        Integer totalNum = baseOnSaleResVO.getTotalNum();
        String bbName = baseOnSaleResVO.getBbName();

        //分页在售商品信息
        LambdaQueryWrapper<BlindBoxMallEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(BlindBoxMallEntity::getBbId, blindBoxOnSaleQuery.getId())
                .eq(BlindBoxMallEntity::getStatus, PmsCommonConstant.BLIND_BOX_CONSING)
                .or()
                .eq(BlindBoxMallEntity::getStatus, PmsCommonConstant.BLIND_BOX_LOCKED);
        if (CharSequenceUtil.isBlank(blindBoxOnSaleQuery.getOrderField())) {
            queryWrapper.orderByAsc(BlindBoxMallEntity::getSellingPrice);
        } else {
            //设置默认条件以及兜底 阻止恶意构造请求
            this.constructSql(blindBoxOnSaleQuery, queryWrapper);
        }

        IPage<BlindBoxMallEntity> page = this.page(
                new PageQuery<BlindBoxMallEntity>().getPage(blindBoxOnSaleQuery),
                queryWrapper
        );
        if (CollUtil.isEmpty(page.getRecords())) {
            BlindBoxOnSalePageResVO blindBoxOnSalePageResVO = new BlindBoxOnSalePageResVO();
            blindBoxOnSalePageResVO.setBlindBoxBaseOnSaleResVO(baseOnSaleResVO);
            blindBoxOnSalePageResVO.setPageData(new PageData<>(Collections.emptyList(), 0));
            return blindBoxOnSalePageResVO;
        }
        List<BlindBoxOnSaleResVO> blindBoxOnSaleResVOS = BeanUtil.copyToList(page.getRecords(), BlindBoxOnSaleResVO.class);
        blindBoxOnSaleResVOS.forEach(c -> {
            c.setBlindBoxSerialNum(String.format(CommonConstant.SERIAL_NUM, c.getSerialNum(), totalNum));
            c.setBbName(String.format(CommonConstant.PRODUCT_NAME, bbName, c.getSerialNum()));
        });
        PageData<BlindBoxOnSaleResVO> blindBoxOnSaleResVOData = new PageData<>(blindBoxOnSaleResVOS, page.getTotal());
        BlindBoxOnSalePageResVO blindBoxOnSalePageResVO = new BlindBoxOnSalePageResVO();
        blindBoxOnSalePageResVO.setBlindBoxBaseOnSaleResVO(baseOnSaleResVO);
        blindBoxOnSalePageResVO.setPageData(blindBoxOnSaleResVOData);
        return blindBoxOnSalePageResVO;
    }

    @Override
    public BlindBoxOnSaleDetailResVO getOnSaleBlindBoxDetail(Long id) {
        //在售信息
        BlindBoxMallEntity byId = this.getById(id);
        //基础信息
        BlindBoxBaseEntity blindBoxBase = this.cacheBlindBoxBaseInfo(byId.getBbId());

        BlindBoxOnSaleDetailResVO blindBoxOnSaleDetailResVO = new BlindBoxOnSaleDetailResVO();
        BeanUtil.copyProperties(blindBoxBase, blindBoxOnSaleDetailResVO);
        blindBoxOnSaleDetailResVO.setCollectionName(String.format(CommonConstant.PRODUCT_NAME, blindBoxBase.getBbName(), byId.getSerialNum()));
        blindBoxOnSaleDetailResVO.setBlindBoxSerialNum(String.format(CommonConstant.SERIAL_NUM, byId.getSerialNum(), blindBoxBase.getTotalNum()));

        blindBoxOnSaleDetailResVO.setStatus(byId.getStatus());
        blindBoxOnSaleDetailResVO.setSellerId(byId.getSellerId());
        blindBoxOnSaleDetailResVO.setSerialNum(byId.getSerialNum());
        blindBoxOnSaleDetailResVO.setSellingPrice(byId.getSellingPrice());

        //账号信息
        R<UserBaseEntity> baseInfoById = userService.getUserBaseInfoById(byId.getSellerId(), SecurityConstant.FROM_IN);
        UserBaseEntity userBaseEntity = OpsUtil
                .of(baseInfoById)
                .assertDataNotNull(e -> new FastException("获取用户信息失败"))
                .getData()
                .get();

        blindBoxOnSaleDetailResVO.setUsername(userBaseEntity.getUsername());
        blindBoxOnSaleDetailResVO.setOffshoreAccount(userBaseEntity.getOffshoreAccount());
        blindBoxOnSaleDetailResVO.setAccountType(userBaseEntity.getAccountType());

        return blindBoxOnSaleDetailResVO;
    }

    @Override
    public boolean blindBoxesOnConsign(List<UserBlindBoxHoldEntity> userBlindBoxHoldList) {
        List<BlindBoxMallEntity> list = new ArrayList<>(16);
        userBlindBoxHoldList.forEach(c -> {
            BlindBoxMallEntity mallEntity = new BlindBoxMallEntity();
            if (Objects.nonNull(c.getConsignId())) {
                mallEntity.setId(c.getConsignId());
            }
            mallEntity.setBbId(c.getBbId());
            mallEntity.setSellerId(c.getUserId());
            mallEntity.setSerialNum(c.getSerialNum());
            mallEntity.setSellingPrice(c.getSellingPrice());
            mallEntity.setPurchasePrice(c.getPurchasePrice());
            mallEntity.setStatus(PmsCommonConstant.BLIND_BOX_CONSING);
            list.add(mallEntity);
        });
        //TODO 记录日志
        return this.saveOrUpdateBatch(list, 50);
    }

    private BlindBoxBaseEntity cacheBlindBoxBaseInfo(Long bbId) {
        BlindBoxBaseEntity blindBoxBase;
        if (Objects.nonNull(redisUtil.getObject(String.format(PmsCacheConstant.BLIND_BOX_BASE, bbId)))) {
            blindBoxBase = (BlindBoxBaseEntity) redisUtil.getObject(String.format(PmsCacheConstant.BLIND_BOX_BASE, bbId));
        } else {
            //获取盲盒基础信息
            blindBoxBase = blindBoxBaseService.getById(bbId);
            redisUtil.setValue(String.format(PmsCacheConstant.BLIND_BOX_BASE, bbId), blindBoxBase, 12, TimeUnit.HOURS);
        }
        return blindBoxBase;
    }

    private void constructSql(BlindBoxOnSaleQuery blindBoxOnSaleQuery, LambdaQueryWrapper<BlindBoxMallEntity> queryWrapper) {
        if (blindBoxOnSaleQuery.getOrderField().equals("sellingPrice")) {
            if (blindBoxOnSaleQuery.getOrder().equals(CommonConstant.ASC)) {
                queryWrapper.orderByAsc(BlindBoxMallEntity::getSellingPrice);
            } else {
                queryWrapper.orderByDesc(BlindBoxMallEntity::getSellingPrice);
            }
        } else if (blindBoxOnSaleQuery.getOrderField().equals("serialNum")) {
            if (blindBoxOnSaleQuery.getOrder().equals(CommonConstant.ASC)) {
                queryWrapper.orderByAsc(BlindBoxMallEntity::getSerialNum);
            } else {
                queryWrapper.orderByDesc(BlindBoxMallEntity::getSerialNum);
            }
        } else {
            queryWrapper.orderByAsc(BlindBoxMallEntity::getSellingPrice);
        }
        blindBoxOnSaleQuery.setOrderField(null);
    }

}